package com.keter.framework.core.result;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.keter.framework.core.exception.ValidateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * JSON结果集：封装Ajax请求，给出JSON形式统一的结果格式
 * Created by gulx@neusoft.com on 2019/3/3.
 */
public class JSONResult extends JSONObject{
    /*结果集封装常量*/
    public final static String KEY_STATUS = "status";
    private boolean EMPTY = false;
    public final static String KEY_DATA = "data";
    public final static String KEY_CODE = "code";
    public final static String KEY_ERROR = "error";
    public final static String KEY_CAUSE = "cause";

    private static final Logger logger = LoggerFactory.getLogger(JSONResult.class);

    public  JSONResult(){
        this.put(JSONResult.KEY_STATUS, JSONResult.Status.OK.value());
    }

    public  static JSONResult emptyResult(){
        JSONResult result = new JSONResult();
        result.EMPTY = true;
        return result;
    }

    /**
     * 判定结果是否正确
     *
     * @return
     */
    public boolean isOK() {
        return Status.OK.value().equals(status());
    }

    public boolean isError() {
        return Status.ERROR.value().equals(status());
    }

    /**
     * 判断结果集内容是否为空：空对象、空字符串、空(长度为0)的数组均被判定为空！
     * @return
     */
    @Override
    public boolean isEmpty() {
        if(this.EMPTY){
            return true;
        }
        if(this.data()==null){
            return true;
        }
        if (this.data() instanceof JSONObject){
            return this.object()==null;
        }
        if (this.data() instanceof JSONArray){
            return this.array()==null || this.array().size()==0;
        }
        if (this.data() instanceof String){
            return Strings.isNullOrEmpty(this.string());
        }
        return false;
    }

    /**
     * 获取结果错误信息
     *
     * @return
     */
    public String error() {
        return this.getString(KEY_ERROR);
    }

    /**
     * 获取结果错误代码
     *
     * @return
     */
    public int code() {
        return this.getIntValue(KEY_CODE);
    }

    /**
     * 自动转换类型的结果集：对于List类统一转换成JSONArray
     * @param <T>
     * @return
     */
    public  <T> T data() {
        Object value = this.get(KEY_DATA);
        // 处理远程调用时，JSONObject对象被转换成LinkedHashMap问题
        if (value instanceof Map) {
            value = new JSONObject((Map) value);
        }
        // 处理远程调用时，JSONArray对象被转换成List问题
        if (value instanceof List) {
            value = new JSONArray((List) value);
        }
        return (T) value;
    }

    /**
     * 返回结果数据，缺省为JSONObject类型
     *
     * @return
     */
    public JSONObject object() {
        return this.getJSONObject(KEY_DATA);
    }

    /**
     * 返回String类型的结果数据
     *
     * @return
     */
    public String string() {
        return this.getString(KEY_DATA);
    }

    public String string(String key) {
        JSONObject o =  this.data();
        return o.getString(key);
    }

    /**
     * 返回Json Array类型的结果数据
     *
     * @return
     */
    public JSONArray array() {
        return this.getJSONArray(KEY_DATA);
    }

    private String status() {
        return this.getString(KEY_STATUS);
    }

    /**
     * 保证结果集的正确性：结果集错误时抛出异常并附加默认的错误消息
     *
     * @return
     */
    public JSONResult ensure() {
        return ensure("");
    }

    /**
     * 结果集错误时抛出异常，并附加自定义的错误消息
     *
     * @return
     */
    public JSONResult ensure(String message) {
        if (this.isError()) {
            logger.error("调用出错！原始错误信息:{},原始错误代码：{}", this.error(), this.code());
            if (Strings.isNullOrEmpty(message)) {
                throw new ValidateException(this.error(), this.code());
            }
            throw new ValidateException(message, this.code());
        }
        return this;
    }

    public enum Status {
        /**
         * 成功
         */
        OK(0),
        ERROR(1),
        // 空对象标识
        NULL(2);
        private int nCode;

        Status(int _nCode) {
            this.nCode = _nCode;
        }

        public String value() {
            return String.valueOf(this.nCode);
        }

        @Override
        public String toString() {
            return value();
        }
    }

    /**
     * 不建议直接使用JSONObject的getXXX方法，大多数情况下属于取值错误行为！
     * @param key
     * @return
     */
    @Override
    @Deprecated
    public Object get(Object key) {
      return super.get(key);
    }

}
